<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <title>HTTP Request参数传递</title>
  
    <meta name="author" content="秀才">

    <!-- Le HTML5 shim, for IE6-8 support of HTML elements -->
    <!--[if lt IE 9]>
      <script src="http://html5shim.googlecode.com/svn/trunk/html5.js"></script>
    <![endif]-->

    <!-- Le styles -->
    <link href="/assets/twitter/stylesheets/bootstrap.min.css" type="text/css" rel="stylesheet" media="all">
<link href="/assets/twitter/stylesheets/style.css" type="text/css" rel="stylesheet" media="all">
 
    <link href="/assets/twitter/widgets/google_prettify/stylesheets/twitter-bootstrap.css" type="text/css" rel="stylesheet" media="all">

    <!-- Le fav and touch icons -->
  <!-- Update these with your own images
    <link rel="shortcut icon" href="images/favicon.ico">
    <link rel="apple-touch-icon" href="images/apple-touch-icon.png">
    <link rel="apple-touch-icon" sizes="72x72" href="images/apple-touch-icon-72x72.png">
    <link rel="apple-touch-icon" sizes="114x114" href="images/apple-touch-icon-114x114.png">
  -->
  </head>

  <body>

    <div class="navbar">
      <div class="navbar-inner">
        <div class="container">
          <a class="brand" href="/">秀才</a>
          <ul class="nav">
            
              


  <li><a href="/tags">标签</a></li>


            
              


  <li><a href="/categories">分类</a></li>


            
              


  <li><a href="/about">关于我</a></li>


            
          </ul>
        </div>
      </div>
    </div>

    <div class="container">
      <div class="content">
        <div class="page-header">
  <h1>HTTP Request参数传递 </h1>
</div>

<div class="row">
  <div class="span12">
    <h3>url传参</h3>

<p>这种在各种method（get，post，delete，put）都能使用，解析速度快</p>

<h3>application/x-www-form-urlencoded</h3>

<p>这应该是最常见的 POST 提交数据的方式了。浏览器的原生 <form> 表单，如果不设置 enctype 属性，那么最终就会以 application/x-www-form-urlencoded 方式提交数据。请求类似于下面这样（无关的请求头在本文中都省略掉了）：</p>

<pre><code>POST http://www.example.com HTTP/1.1
Content-Type: application/x-www-form-urlencoded;charset=utf-8

title=test&amp;sub%5B%5D=1&amp;sub%5B%5D=2&amp;sub%5B%5D=3
</code></pre>

<p>首先，Content-Type 被指定为 application/x-www-form-urlencoded；其次，提交的数据按照 key1=val1&amp;key2=val2 的方式进行编码，key 和 val 都进行了 URL 转码。大部分服务端语言都对这种方式有很好的支持。例如 PHP 中，$_POST[&lsquo;title&rsquo;] 可以获取到 title 的值，$_POST[&lsquo;sub&rsquo;] 可以得到 sub 数组。</p>

<p>很多时候，我们用 Ajax 提交数据时，也是使用这种方式。例如 JQuery 和 QWrap 的 Ajax，Content-Type 默认值都是「application/x-www-form-urlencoded;charset=utf-8」。</p>

<h3>multipart/form-data</h3>

<p>这又是一个常见的 POST 数据提交的方式。我们使用表单上传文件时，必须让 <form> 表单的 enctype 等于 multipart/form-data。直接来看一个请求示例：</p>

<pre><code>POST http://www.example.com HTTP/1.1
Content-Type:multipart/form-data; boundary=----WebKitFormBoundaryrGKCBY7qhFd3TrwA

------WebKitFormBoundaryrGKCBY7qhFd3TrwA
Content-Disposition: form-data; name=&quot;text&quot;

title
------WebKitFormBoundaryrGKCBY7qhFd3TrwA
Content-Disposition: form-data; name=&quot;file&quot;; filename=&quot;chrome.png&quot;
Content-Type: image/png

PNG ... content of chrome.png ...
------WebKitFormBoundaryrGKCBY7qhFd3TrwA--
</code></pre>

<p>这个例子稍微复杂点。首先生成了一个 boundary 用于分割不同的字段，为了避免与正文内容重复，boundary 很长很复杂。然后 Content-Type 里指明了数据是以 multipart/form-data 来编码，本次请求的 boundary 是什么内容。消息主体里按照字段个数又分为多个结构类似的部分，每部分都是以 --boundary 开始，紧接着是内容描述信息，然后是回车，最后是字段具体内容（文本或二进制）。如果传输的是文件，还要包含文件名和文件类型信息。消息主体最后以 --boundary-- 标示结束。关于 multipart/form-data 的详细定义，请前往 rfc1867 查看。</p>

<p>这种方式一般用来上传文件，各大服务端语言对它也有着良好的支持。</p>

<p>上面提到的这两种 POST 数据的方式，都是浏览器原生支持的，而且现阶段标准中原生 <form> 表单也只支持这两种方式（通过 <form> 元素的 enctype 属性指定，默认为 application/x-www-form-urlencoded。其实 enctype 还支持 text/plain，不过用得非常少）。</p>

<p>随着越来越多的 Web 站点，尤其是 WebApp，全部使用 Ajax 进行数据交互之后，我们完全可以定义新的数据提交方式，给开发带来更多便利。</p>

<h3>application/json</h3>

<p>application/json 这个 Content-Type 作为响应头大家肯定不陌生。实际上，现在越来越多的人把它作为请求头，用来告诉服务端消息主体是序列化后的 JSON 字符串。由于 JSON 规范的流行，除了低版本 IE 之外的各大浏览器都原生支持 JSON.stringify，服务端语言也都有处理 JSON 的函数，使用 JSON 不会遇上什么麻烦。</p>

<p>JSON 格式支持比键值对复杂得多的结构化数据，这一点也很有用。记得我几年前做一个项目时，需要提交的数据层次非常深，我就是把数据 JSON 序列化之后来提交的。不过当时我是把 JSON 字符串作为 val，仍然放在键值对里，以 x-www-form-urlencoded 方式提交。</p>

<pre><code class="language-json">POST http://www.example.com HTTP/1.1 
Content-Type: application/json;charset=utf-8

{&quot;title&quot;:&quot;test&quot;,&quot;sub&quot;:[1,2,3]}
</code></pre>

<p>这种方案，可以方便的提交复杂的结构化数据，特别适合 RESTful 的接口。各大抓包工具如 Chrome 自带的开发者工具、Firebug、Fiddler，都会以树形结构展示 JSON 数据，非常友好。但也有些服务端语言还没有支持这种方式，例如 php 就无法通过 $_POST 对象从上面的请求中获得内容。这时候，需要自己动手处理下：在请求头中 Content-Type 为 application/json 时，从 php://input 里获得原始输入流，再 json_decode 成对象。一些 php 框架已经开始这么做了。</p>

<h3>text/xml</h3>

<blockquote>
<p>本人对此格式有成见，就不赘述了。</p>
</blockquote>

    <hr>
    <div class="pagination">
      <ul>
        <ul>
          
            <li class="prev"><a href="/http/HTTP-%E5%B9%B6%E5%8F%91%E6%A6%82%E5%BF%B5/" title="HTTP 并发概念">&larr; Previous</a></li>
          
          

            <li><a href="/archive">Archive</a></li>

          
          
            <li class="next disabled"><a>Next &rarr;</a>
          
        </ul>
      </ul>
    </div>
    <hr>
    
  </div>
  
  <!-- <div class="span4">
    <h4>Published</h4>
    <div class="date"><span>2015-07-01</span></div>
    <br>
    <h4>Categories</h4>
    <ul class="tag_box">
    
      <li>
  <a href="/categories/#http-ref">http <span>2</span></a>
</li>
    
    </ul>
    <br>
    <h4>Tags</h4>
    <ul class="tag_box">
    
      <li>
  <a href="/tags/#http-ref">http <span>2</span></a>
</li>
    
    </ul>
  </div> -->
</div>

      </div>

      <footer>
        <p>&copy; 秀才 2013 
          with help from <a href="http://github.com/wendal/gor" target="_blank" title="Gor -- Fast Blog">Gor</a>
          and <a href="http://twitter.github.com/bootstrap/" target="_blank">Twitter Bootstrap</a>
		  and Idea from <a href="http://ruhoh.com" target="_blank" title="The Definitive Technical Blogging Framework">ruhoh</a>
        </p>
      </footer>

    </div> <!-- /container -->
    <!-- <script src="//cdnjscn.b0.upaiyun.com/libs/prettify/r298/prettify.min.js"></script> -->
    <script src="http://cdn.staticfile.org/prettify/r298/prettify.min.js"></script>
    <script>
      var pres = document.getElementsByTagName("pre");
      for (var i=0; i < pres.length; ++i) {
        pres[i].className = "prettyprint linenums";
      }
      prettyPrint();
    </script>
    
    
  </body>
</html>
